import { jsapi, viewUtils } from '@/utils/arcgis';
import echarts from 'echarts';

let EchartsLayerCache = null;

// 单例
async function getEchartsLayer() {
  const [SpatialReference] = await jsapi.load(['esri/geometry/SpatialReference']);
  const view = await viewUtils.isViewReady();

  // 生成坐标系统
  /**
   * 生成echarts额外的坐标细用于注册
   * @param {*} map 地图view实例
   * @param {*} dimensions
   * @param {*} coordinateSystemName 坐标系统名称
   */
  function getCoordinateSystem(
    map,
    dimensions = ['lng', 'lat'],
    coordinateSystemName = 'arcgis_geo',
  ) {
    function CoordSystem(map) {
      this.map = map;
      this._mapOffset = [0, 0];
    }
    CoordSystem.create = function(ecModel) {
      ecModel.eachSeries(function(seriesModel) {
        if (seriesModel.get('coordinateSystem') === coordinateSystemName) {
          seriesModel.coordinateSystem = new CoordSystem(map);
        }
      });
    };
    CoordSystem.getDimensionsInfo = function() {
      return dimensions;
    };
    CoordSystem.dimensions = dimensions;
    CoordSystem.prototype.dimensions = dimensions;
    CoordSystem.prototype.setMapOffset = function setMapOffset(mapOffset) {
      this._mapOffset = mapOffset;
    };
    CoordSystem.prototype.dataToPoint = function dataToPoint(data) {
      var point = {
        type: 'point',
        x: data[0],
        y: data[1],
        spatialReference: new SpatialReference(4326),
        // spatialReference: new SpatialReference({ wkid: 4326 }),
        // spatialReference: { wkid: 4326 },
      };
      var px = map.toScreen(point);
      var mapOffset = this._mapOffset;
      return [px.x - mapOffset[0], px.y - mapOffset[1]];
    };
    CoordSystem.prototype.pointToData = function pointToData(pt) {
      var mapOffset = this._mapOffset;
      var screentPoint = {
        x: pt[0] + mapOffset[0],
        y: pt[1] + mapOffset[1],
      };
      var data = map.toMap(screentPoint);
      return [data.x, data.y];
    };
    CoordSystem.prototype.getViewRect = function getViewRect() {
      return new echarts.graphic.BoundingRect(0, 0, this.map.width, this.map.height);
    };
    CoordSystem.prototype.getRoamTransform = function getRoamTransform() {
      return echarts.matrix.create();
    };
    return CoordSystem;
  }

  if (!EchartsLayerCache) {
    class EchartsLayer {
      constructor(view, option) {
        this.name = 'EchartsLayer';
        this.view = null; // 要覆盖展示的view 容器
        this.box = null; // echarts挂载容器
        this.chart = null; // echart实例
        this.chartOption = null;
        this.visible = true; // 图表是否可见
        this.echartsLib = echarts; // echarts库

        // 地图事件监听函数
        this.mapExtentListener = null;
        this.mapClickListener = null;
        this.mapRotationListener = null;

        this.echartsLib.registerCoordinateSystem(
          'arcgis_geo',
          // getGeoCoordinateSystem(view),
          getCoordinateSystem(view, ['lng', 'lat'], 'arcgis_geo'),
        );
        this.echartsLib.registerCoordinateSystem(
          'arcgis',
          // getE3CoordinateSystem(view),
          getCoordinateSystem(view, ['x', 'y'], 'arcgis'),
        );

        this._init(view, option);
      }

      // 初始化
      _init(view, option) {
        // this.setBaseMap(view);
        this.view = view;
        this._createLayer();
        option && this.setChartOption(option);
      }

      // 由于view在construct时已经用于注册坐标系统 此处重设view也没啥意义
      // setBaseMap(view) {
      //   this.view = view;
      // }

      /*创建layer的容器，添加到map的layers下面*/
      _createLayer() {
        // 创建并挂载echarts容器
        let box = (this.box = document.createElement('div'));
        box.setAttribute('id', Date.now());
        box.style.width = this.view.width + 'px';
        box.style.height = this.view.height + 'px';
        box.style.position = 'absolute';
        box.style.top = 0;
        box.style.left = 0;
        const parent = this.view.container.getElementsByClassName('esri-view-surface')[0];
        parent.appendChild(box);
        console.log(box);

        // 创建echarts实例
        this.chart = this.echartsLib.init(box);
        this._startMapEventListeners();
      }

      // 设置图表参数
      _setCharts() {
        if (this.visible && this.chartOption) {
          let baseExtent = this.view.extent;
          //判断是否使用了mark类型标签，每次重绘要重新转换地理坐标到屏幕坐标
          //* 原理：根据当前地图extent,修改展示容器的x，y轴起始值与终点值，重绘echarts
          try {
            this.chartOption.xAxis = { show: false, min: baseExtent.xmin, max: baseExtent.xmax };
            this.chartOption.yAxis = { show: false, min: baseExtent.ymin, max: baseExtent.ymax };
            this.chart.clear.call(this.chart);
            this.chart.setOption.call(this.chart, this.chartOption);
            this.chartOption.animation = false;
          } catch (error) {
            console.error(error);
          }
        }
      }

      /*监听地图事件，根据图层是否显示，判断是否重绘echarts*/
      _startMapEventListeners() {
        let view = this.view;
        let self = this;
        this.mapExtentListener = view.watch('extent', function(evt) {
          // todo 得加一个地球背后hide的功能
          // console.log('extent----------------', evt);
          if (!self.visible) return;
          self._setCharts();
          // self.chart.resize();
          // self.box.hidden = false;
        });

        // scence的环境下没有用到
        this.mapRotationListener = view.watch('rotation', function() {
          console.log('rotation----------------');
          if (!self.visible) return;
          self._setCharts();
          // self.chart.resize();
          // self.box.hidden = false;
        });

        // todo 感觉没到背面的话也没必要
        // 地图上的点击派发给echarts
        this.mapClickListener = view.on('click', function(e) {
          const _e = e.native;
          console.log('click-------------------');
          let evt = new MouseEvent('click', {
            altKey: _e.altKey,
            button: _e.button,
            buttons: _e.buttons,
            clientX: _e.clientX,
            clientY: _e.clientY,
            ctrlKey: _e.ctrlKey,
            metaKey: _e.metaKey,
            movementX: _e.movementX,
            movementY: _e.movementY,
            offsetX: _e.offsetX,
            offsetY: _e.offsetY,
            pageX: _e.pageX,
            pageY: _e.pageY,
            region: _e.region,
            screenX: _e.screenX,
            screenY: _e.screenY,
            shiftKey: _e.shiftKey,
            which: _e.which,
            x: _e.x,
            y: _e.y,
          });
          self.chart
            .getDom()
            .getElementsByTagName('div')[0]
            .dispatchEvent(evt);
        });
      }

      // setCharts的包装层缓存echart 配置
      setChartOption(option) {
        this.chartOption = option;
        console.log(this.chartOption);
        this._setCharts();
      }

      setVisible(isVisible) {
        const self = this;
        if (!this.box || this.visible === isVisible) {
        } else {
          this.box.hidden = !isVisible;
          this.visible = isVisible;
          isVisible && self._setCharts();
        }
      }

      refreshBegin() {
        this.box.hidden = true;
      }

      refreshing() {
        const self = this;
        self._setCharts();
      }

      refreshEnd() {
        this.box.hidden = false;
      }

      // 注册echarts事件
      on(eventName, handler, context) {
        this.chart.on(eventName, handler, context);
      }
      // 清除echarts事件
      off(eventName, handler, context) {
        this.chart.off(eventName, handler, context);
      }

      /*销毁实例*/
      removeLayer() {
        this.box.outerHTML = '';
        this.view = null;
        this.box = null;
        this.originLyr = null;
        this.features = null;
        this.screenData = [];
        this.chart = null;
        this.chartOption = null;
        this.mapExtentListener.remove();
        this.mapRotationListener.remove();
        this.mapClickListener.remove();

        // this.map_ZoomStart_Listener.remove();
        // this.map_ZoomEnd_Listener.remove();
        // this.map_ExtentChange_Listener.remove();
      }
    }

    EchartsLayerCache = EchartsLayer;
  }

  return EchartsLayerCache;
}

export default getEchartsLayer;
